package com.hexun.vmcenter.service.impl;

import java.io.UnsupportedEncodingException;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.hexun.vmcenter.service.RedisService;

/**
 * Redis service实现类
 * 
 * @author hexun
 */
@Service(value = "redisService")
public class RedisServiceImpl implements RedisService {

    private static String redisCode = "utf-8";
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    /**
     * {@inheritDoc}
     */
	public long del(final String... keys) {
        return redisTemplate.execute(new RedisCallback<Long>() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                long result = 0;
                for (int i = 0; i < keys.length; i++) {
                    result = connection.del(keys[i].getBytes());
                }
                return result;
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
	public void set(final byte[] key, final byte[] value, final long liveTime) {
        redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                connection.set(key, value);
                if (liveTime > 0) {
                    connection.expire(key, liveTime);
                }
                return 1L;
            }
        });
    }

    /**
     * {@inheritDoc}
     */
    public void set(String key, String value, long liveTime) {
        this.set(key.getBytes(), value.getBytes(), liveTime);
    }

    /**
     * {@inheritDoc}
     */
    public void set(String key, String value) {
        this.set(key, value, 0L);
    }

    /**
     * {@inheritDoc}
     */
    public void set(byte[] key, byte[] value) {
        this.set(key, value, 0L);
    }

    /**
     * {@inheritDoc}
     */
	public String get(final String key) {
        return redisTemplate.execute(new RedisCallback<String>() {
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                try {
                	if(connection != null){
                		byte[] bs = connection.get(key.getBytes());
                		if(bs != null && bs.length > 0){
                			return new String(bs, redisCode);
                		}
                	}
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return "";
            }
        });
    }

	public String get(final String key, final String defaultValue) {
		String value = get(key);
		if(value == ""){
			return defaultValue;
		}
		return value;
	}
	
    /**
     * {@inheritDoc}
     */
    public Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);

    }

    /**
     * {@inheritDoc}
     */
	public boolean exists(final String key) {
        return redisTemplate.execute(new RedisCallback<Boolean>() {
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.exists(key.getBytes());
            }
        });
    }

    /**
     * {@inheritDoc}
     */
	public String flushDB() {
        return redisTemplate.execute(new RedisCallback<String>() {
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                connection.flushDb();
                return "ok";
            }
        });
    }

    /**
     * {@inheritDoc}
     */
	public long dbSize() {
        return redisTemplate.execute(new RedisCallback<Long>() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.dbSize();
            }
        });
    }

    /**
     * {@inheritDoc}
     */
	public String ping() {
        return redisTemplate.execute(new RedisCallback<String>() {
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                return connection.ping();
            }
        });
    }
	
	 /**
     * {@inheritDoc}
     */
	public long incrBy(final String key, final long count) {
        return redisTemplate.execute(new RedisCallback<Long>() {
            public Long doInRedis(RedisConnection connection) throws DataAccessException {
            	return connection.incrBy(key.getBytes(), count);
            }
        });
    }
	
	 /**
     * {@inheritDoc}
     */
	public boolean expire(final String key, final long liveTime) {
        return redisTemplate.execute(new RedisCallback<Boolean>() {
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
            	return connection.expire(key.getBytes(), liveTime);
            }
        });
    }

}